package com.github.manx98.okdownloader.utils;

import com.github.manx98.okdownloader.common.TaskStatusType;

import java.util.concurrent.atomic.LongAdder;

/**
 * 任务状态状态
 *
 * @author : manx98
 * @date : 2021/5/26
 */
public class DownloadTaskStatus {
    protected final LongAdder threadCount;
    private volatile long completeSize;
    private volatile TaskStatusType status;
    private volatile long timestamp;
    private long fileSize;
    private volatile long lastTimestamp;
    private volatile long speed;
    private Throwable exception;

    /**
     * 任务状态状态
     *
     * @param fileSize           文件大小
     * @param completeSize       已完成下载的长度
     */
    public DownloadTaskStatus(long fileSize, long completeSize) {
        this.status = TaskStatusType.WAITING;
        this.completeSize = completeSize;
        this.fileSize = fileSize;
        this.threadCount = new LongAdder();
    }

    /**
     * 获取当前任务的状态
     *
     * @return 状态
     */
    public TaskStatusType getStatus() {
        return status;
    }

    /**
     * 设置下载状态
     *
     * @param status 状态
     */
    protected void setStatus(TaskStatusType status) {
        if (status == TaskStatusType.RUNNING) {
            this.speed = 0;
            this.lastTimestamp = this.timestamp = System.currentTimeMillis();
        }
        this.status = status;
    }

    /**
     * <b>获取下载瞬时速度</b><br>
     * 此操作会返回一个<b>long</b>类型的数值，表示<b>byte/s</b>的速度值。如果此时下载任务已经终止，则这个数值将不会再发生变化。
     *
     * @return byte/s
     */
    public synchronized long getSpeed() {
        return speed;
    }

    protected synchronized void setSpeed() {
        this.speed = 0;
    }

    /**
     * 获取下载任务开始时间
     *
     * @return 下载任务开始时间戳
     */
    public long getTimestamp() {
        return timestamp;
    }

    /**
     * 获取已完成的下载长度
     *
     * @return 已下载的文件长度 byte
     */
    public long getCompleteSize() {
        return completeSize;
    }

    /**
     * 修改下载完成的长度
     *
     * @param unCompleteSize 已完成下载的字节数
     */
    protected synchronized void updateUnCompleteSize(long unCompleteSize) {
        long u = this.fileSize - unCompleteSize;
        long t = System.currentTimeMillis();
        this.speed = Math.max(u - this.completeSize, 0) * 1000 / (t - lastTimestamp + 1);
        this.completeSize = u;
        this.lastTimestamp = t;
    }

    /**
     * 获取文件长度
     *
     * @return 文件大小 byte
     */
    public long getFileSize() {
        return fileSize;
    }

    /**
     * 设置文件大小
     *
     * @param fileSize 文件字节数
     */
    protected void setFileSize(long fileSize) {
        this.fileSize = fileSize;
    }

    /**
     * 获取当前线程数量
     *
     * @return 线程数量
     */
    public int getThreadCount() {
        return threadCount.intValue();
    }

    /**
     * 获取执行异常
     *
     * @return 异常
     */
    public Throwable getException() {
        return exception;
    }

    /**
     * 任务执行异常
     *
     * @param exception 异常
     */
    protected void setException(Throwable exception) {
        if (this.exception != null) {
            synchronized (this) {
                if (this.exception != null) {
                    this.exception = exception;
                }
            }
        }
    }

    @Override
    public String toString() {
        return "DownloadTaskStatus{" +
                "status=" + status +
                ", timestamp=" + timestamp +
                ", completeSize=" + completeSize +
                ", fileSize=" + fileSize +
                ", threadCount=" + threadCount +
                '}';
    }

}
